/*
@auther fenglei
*/
package xxpool

import (
	"fmt"
	"reflect"
	"sync"
	"time"

	"github.com/panjf2000/ants/v2"
)

type AntPoolClient struct {
	ExpiryDuration time.Duration //超时时间
}

func NewAntPoolClient() *AntPoolClient {
	http := &AntPoolClient{
		//生成默认值
		60 * time.Second,
	}
	return http
}

// AntPool 增强版，可以处理任何类型的切片
// 参数 listT 可以是 []interface{} 或任何其他类型的切片
func (e *AntPoolClient) AntPool(size int, pff func(interface{}), listT interface{}) error {
	var itemsSlice []interface{}

	// 检查是否已经是 []interface{} 类型
	if items, ok := listT.([]interface{}); ok {
		itemsSlice = items
	} else {
		// 检查是否为其他类型的切片
		v := reflect.ValueOf(listT)
		if v.Kind() != reflect.Slice {
			return fmt.Errorf("listT 必须是切片类型，得到的是 %T", listT)
		}

		// 将切片转换为 []interface{}
		length := v.Len()
		itemsSlice = make([]interface{}, length)
		for i := 0; i < length; i++ {
			// 这应该保留原始值，包括它是否为指针
			itemsSlice[i] = v.Index(i).Interface()
		}
	}

	// 执行并行处理
	defer ants.Release()
	var wg sync.WaitGroup
	options := ants.Options{}
	options.ExpiryDuration = e.ExpiryDuration
	options.PreAlloc = true

	p, err := ants.NewPoolWithFunc(size, func(i interface{}) {
		pff(i)
		wg.Done()
	}, ants.WithOptions(options))

	if err != nil {
		return fmt.Errorf("failed to create pool: %v", err)
	}
	defer p.Release()

	for _, v := range itemsSlice {
		wg.Add(1)
		_ = p.Invoke(v)
	}
	wg.Wait()
	return nil
}

// AntPoolWithResult 增强版，可以处理任何类型的切片并收集处理结果
// 参数 listT 可以是 []interface{} 或任何其他类型的切片
// processor 函数可以返回任意类型的值，这些值将被收集并返回
func (e *AntPoolClient) AntPoolWithResult(size int, processor func(interface{}) interface{}, listT interface{}) ([]interface{}, error) {
	var itemsSlice []interface{}

	// 检查是否已经是 []interface{} 类型
	if items, ok := listT.([]interface{}); ok {
		itemsSlice = items
	} else {
		// 检查是否为其他类型的切片
		v := reflect.ValueOf(listT)
		if v.Kind() != reflect.Slice {
			return nil, fmt.Errorf("listT 必须是切片类型，得到的是 %T", listT)
		}

		// 将切片转换为 []interface{}
		length := v.Len()
		itemsSlice = make([]interface{}, length)
		for i := 0; i < length; i++ {
			// 这应该保留原始值，包括它是否为指针
			itemsSlice[i] = v.Index(i).Interface()
		}
	}

	// 创建一个切片来存储结果
	results := make([]interface{}, len(itemsSlice))
	resultsMutex := &sync.Mutex{} // 用于保护结果切片的并发访问

	defer ants.Release()
	var wg sync.WaitGroup
	options := ants.Options{}
	options.ExpiryDuration = e.ExpiryDuration
	options.PreAlloc = true

	// 创建一个包含索引和项目的结构体
	type indexedItem struct {
		index int
		item  interface{}
	}

	p, err := ants.NewPoolWithFunc(size, func(i interface{}) {
		// 解包索引和项目
		idxItem := i.(indexedItem)
		idx := idxItem.index
		item := idxItem.item

		// 调用处理函数并获取结果
		result := processor(item)

		// 安全地存储结果
		resultsMutex.Lock()
		results[idx] = result
		resultsMutex.Unlock()

		wg.Done()
	}, ants.WithOptions(options))

	if err != nil {
		return nil, fmt.Errorf("failed to create pool: %v", err)
	}
	defer p.Release()

	// 提交任务，包含索引信息
	for i, v := range itemsSlice {
		wg.Add(1)
		_ = p.Invoke(indexedItem{index: i, item: v})
	}

	wg.Wait()
	return results, nil
}
